package com.destin.basic.exception;

import cn.hutool.core.collection.CollUtil;
import com.destin.basic.util.JsonResponse;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.StringUtils;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.sql.SQLSyntaxErrorException;
import java.util.List;
import java.util.Set;


@Slf4j
@ControllerAdvice
@Primary
public class GlobalExceptionHandler {
    private static final String ERROR_PARAM = "参数出错：{}";
    private static final String PARAMS_VALIDATED_ERROR_MESSAGE = "参数校验异常";

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public JsonResponse badArgumentHandler(IllegalArgumentException e) {
        log.error(ERROR_PARAM, e.getMessage(),e);
        return JsonResponse.error("参数错误");
    }


    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public JsonResponse<String> badArgumentHandler(MethodArgumentTypeMismatchException e) {
        log.error(ERROR_PARAM, e.getMessage(),e);
        return JsonResponse.error("参数错误");
    }

    @ResponseBody
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public JsonResponse<String> httpMethodArgumentValidExceptionHander(MethodArgumentNotValidException exception) {
        log.error("{}: {}", PARAMS_VALIDATED_ERROR_MESSAGE , exception.getMessage(),exception);
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        if (CollUtil.isEmpty(fieldErrors)){
            ObjectError objectError = exception.getBindingResult().getAllErrors().get(0);
            if (objectError != null) {
                return JsonResponse.error(objectError.getDefaultMessage());
            }
            return JsonResponse.error(PARAMS_VALIDATED_ERROR_MESSAGE);
        }
        FieldError error = fieldErrors.get(0);
        if (error != null) {
            return JsonResponse.error(error.getDefaultMessage());
        }
        return JsonResponse.error(PARAMS_VALIDATED_ERROR_MESSAGE);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public JsonResponse<String> badArgumentHandler(MissingServletRequestParameterException e) {
        log.error(ERROR_PARAM, e.getMessage(),e);
        return JsonResponse.error("缺少必要参数错误");
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public JsonResponse<String> badArgumentHandler(HttpMessageNotReadableException e) {
        log.error(ERROR_PARAM, e.getMessage(),e);
        return JsonResponse.error("未知异常,"+e.getMessage());
    }

    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public JsonResponse<String> badArgumentHandler(ValidationException e) {
        log.error(ERROR_PARAM, e.getMessage(),e);
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                String message = ((PathImpl) item.getPropertyPath()).getLeafNode().getName() + item.getMessage();
                log.error(ERROR_PARAM, message,e);
                if (!StringUtils.isEmpty(message)) {
                    return JsonResponse.error(e.getMessage());
                }
            }
        }
        return JsonResponse.error(PARAMS_VALIDATED_ERROR_MESSAGE);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public JsonResponse<String> seriousHandler(BusinessException e) {
        log.error("业务操作异常：{}", e.getMessage(),e);
        return JsonResponse.error("业务操作异常");
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JsonResponse<String> seriousHandler(Exception e) {
        log.error("通用操作异常：{}", e.getMessage(),e);
        return JsonResponse.error("未知异常, 请联系管理员");
    }

//    @ExceptionHandler(ServiceException.class)
//    @ResponseBody
//    public JsonResponse<String> seriousHandler(ServiceException e) {
//        log.error("服务层操作异常：{}", e.getMessage(),e);
//        return JsonResponse.error(e.getMessage());
//    }

    @ExceptionHandler(SQLSyntaxErrorException.class)
    @ResponseBody
    public JsonResponse<String> seriousHandler(SQLSyntaxErrorException e) {
        log.error("数据库执行异常：{}", e.getMessage(),e);
        return JsonResponse.error("数据库执行异常");
    }

}
